<template>
  <view class="fu-drag-popup" :class="{ 'is-visible': show }">
    <!-- 遮罩层 -->
    <view 
      v-if="overlay"
      class="fu-drag-popup__overlay"
      :style="{ 
        'background-color': overlayColor,
        'opacity': overlayOpacity
      }"
      @tap="onClickOverlay"
    ></view>
    
    <!-- 内容区域 -->
    <view 
      class="fu-drag-popup__content"
      :style="{ 
        height: `${currentHeight}rpx`,
        transform: `translateY(${contentTranslateY}px)`,
        transition: dragging ? 'none' : 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
      }"
    >
      <!-- 拖动条 -->
      <view 
        class="fu-drag-popup__drag-bar"
        @touchstart="onTouchStart"
        @touchmove="onTouchMove"
        @touchend="onTouchEnd"
      ></view>
      
      <!-- 内容插槽 -->
      <scroll-view 
        class="fu-drag-popup__body"
        scroll-y
      >
        <slot></slot>
      </scroll-view>
    </view>
  </view>
</template>

<script>
/**
 * @description 可拖动的底部弹框组件
 * @property {Boolean} show 是否显示弹框
 * @property {Boolean} overlay 是否显示遮罩层
 * @property {String} overlay-color 遮罩层颜色
 * @property {Number} content-height 内容区域高度，单位rpx
 * @property {Number} threshold 关闭阈值，拖动超过此距离时关闭
 * @property {Boolean} close-on-click-overlay 是否点击遮罩层关闭
 * @event {Function} close 关闭弹框时触发
 */
export default {
  name: 'FuDragPopup',
  
  props: {
    // 是否显示弹框
    show: {
      type: Boolean,
      default: false
    },
    // 是否显示遮罩层
    overlay: {
      type: Boolean,
      default: true
    },
    // 遮罩层颜色
    overlayColor: {
      type: String,
      default: 'rgba(0, 0, 0, 0.7)'
    },
    // 内容区域高度
    contentHeight: {
      type: Number,
      default: 800
    },
    // 关闭阈值
    threshold: {
      type: Number,
      default: 100
    },
    // 是否点击遮罩层关闭
    closeOnClickOverlay: {
      type: Boolean,
      default: true
    }
  },
  
  data() {
    return {
      dragging: false,
      startY: 0,
      translateY: 0,
      startTranslateY: 0,
      overlayOpacity: 1,
      closing: false,
      currentHeight: 0,
      startHeight: 0,
      lastValidHeight: 0,
      isExpanded: false
    }
  },
  
  computed: {
    // 计算内容区域的实际位移
    contentTranslateY() {
      if (!this.show && !this.closing) {
        return this.contentHeight
      }
      return this.translateY
    }
  },
  
  watch: {
    show(val) {
      if (val) {
        this.translateY = 0
        this.overlayOpacity = 1
        this.closing = false
        this.currentHeight = this.contentHeight
        this.lastValidHeight = this.contentHeight
        this.isExpanded = false
      }
    }
  },
  
  methods: {
    // 点击遮罩层
    onClickOverlay() {
      if (this.closeOnClickOverlay) {
        this.closeWithAnimation()
      }
    },
    
    // 带动画的关闭
    closeWithAnimation() {
      this.closing = true
      this.translateY = this.contentHeight
      this.overlayOpacity = 0
      setTimeout(() => {
        this.$emit('close')
      }, 300)
    },
    
    // 开始拖动
    onTouchStart(e) {
      this.dragging = true
      this.startY = e.touches[0].clientY
      this.startTranslateY = this.translateY
      this.currentHeight = this.lastValidHeight || this.contentHeight
      this.startHeight = this.currentHeight
    },
    
    // 拖动中
    onTouchMove(e) {
      if (!this.dragging) return
      
      const touchY = e.touches[0].clientY
      const distance = touchY - this.startY
      
      // 阻止默认行为
      e.preventDefault()
      
      if (distance < 0) {
        // 向上拖动
        if (!this.isExpanded) {
          const heightDelta = Math.abs(distance)
          this.currentHeight = this.startHeight + heightDelta * 0.5
          this.translateY = 0
        }
      } else {
        // 向下拖动
        if (this.isExpanded) {
          // 如果是展开状态，先恢复到初始高度
          const heightDelta = Math.min(distance, this.currentHeight - this.contentHeight)
          const newHeight = this.startHeight - heightDelta
          
          if (newHeight <= this.contentHeight) {
            // 已经收缩到初始高度
            this.currentHeight = this.contentHeight
            this.isExpanded = false
            // 继续向下拖动时计算位移
            const remainingDistance = distance - heightDelta
            if (remainingDistance > 0) {
              this.translateY = Math.pow(remainingDistance, 0.8)
            }
          } else {
            // 还在收缩过程中
            this.currentHeight = newHeight
            this.translateY = 0
          }
        } else {
          // 未展开状态，直接计算位移
          this.translateY = this.startTranslateY + Math.pow(distance, 0.8)
          this.currentHeight = this.contentHeight
        }
      }
      
      // 限制最大高度
      const maxHeight = uni.getSystemInfoSync().windowHeight * 0.9
      const maxRpxHeight = maxHeight * (750 / uni.getSystemInfoSync().windowWidth)
      if (this.currentHeight > maxRpxHeight) {
        this.currentHeight = maxRpxHeight
      }
      
      // 只在未展开状态且向下拖动时调整遮罩层透明度
      if (!this.isExpanded && this.translateY > 0) {
        const progress = Math.min(this.translateY / this.threshold, 1)
        this.overlayOpacity = 1 - progress * 0.5
      }
    },
    
    // 结束拖动
    onTouchEnd() {
      if (!this.dragging) return
      
      this.dragging = false
      
      // 判断是否超过关闭阈值
      if (!this.isExpanded && this.translateY >= this.threshold) {
        this.closeWithAnimation()
      } else {
        // 保持当前高度
        this.translateY = 0
        this.lastValidHeight = this.currentHeight
        this.overlayOpacity = 1
        // 更新展开状态
        this.isExpanded = this.currentHeight > this.contentHeight
      }
    }
  }
}
</script>

<style lang="scss">
.fu-drag-popup {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  visibility: hidden;
  z-index: 999;
  
  &.is-visible {
    visibility: visible;
  }
  
  &__overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    transition: opacity 0.3s;
  }
  
  &__content {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    background: #fff;
    border-radius: 24rpx 24rpx 0 0;
    will-change: transform;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    
    .is-visible & {
      transform: translateY(0);
    }
  }
  
  &__drag-bar {
    position: relative;
    flex-shrink: 0;
    height: 80rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: grab;
    touch-action: none; // 禁用默认触摸行为
    
    &::after {
      content: '';
      width: 60rpx;
      height: 6rpx;
      background: #dcdee0;
      border-radius: 3rpx;
    }
  }
  
  &__body {
    flex: 1;
    overflow: hidden;
  }
}
</style> 